ble: ap807: Switch to PLL mode and update CPU frequency
authorChristine Gharzuzi <[email protected]>
Mon, 25 Jun 2018 10:39:37 +0000 (13:39 +0300)
committerKonstantin Porotchkin <[email protected]>
Tue, 4 Dec 2018 12:09:44 +0000 (14:09 +0200)
- Update CPU frequency on AP807 to 2GHz for SAR 0x0.
- Increase AVS to 0.88V for 2GHz clock

Change-Id: Ic945b682ab2f8543e34294bfc56c3eae2c5e0c8e
Signed-off-by: Christine Gharzuzi <[email protected]>
Signed-off-by: Konstantin Porotchkin <[email protected]>
drivers/marvell/ap807_clocks_init.c [new file with mode: 0644]
include/drivers/marvell/ap807_clocks_init.h [new file with mode: 0644]
plat/marvell/a8k/common/a8k_common.mk
plat/marvell/a8k/common/plat_ble_setup.c

diff --git a/drivers/marvell/ap807_clocks_init.c b/drivers/marvell/ap807_clocks_init.c
new file mode 100644 (file)
index 0000000..841e6ae
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#include <a8k_plat_def.h>
+#include <aro.h>
+#include <delay_timer.h>
+#include <mmio.h>
+
+/* Notify bootloader on DRAM setup */
+#define AP807_CPU_ARO_CTRL(cluster)    \
+                       (MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster)))
+
+/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
+#define AP807_CPU_ARO_CLK_EN_OFFSET    0
+#define AP807_CPU_ARO_CLK_EN_MASK      (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
+
+/* 0 - ARO is the clock source, 1 - PLL is the clock source */
+#define AP807_CPU_ARO_SEL_PLL_OFFSET   5
+#define AP807_CPU_ARO_SEL_PLL_MASK     (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
+
+/* AP807 clusters count */
+#define AP807_CLUSTER_NUM              2
+
+/* PLL frequency values */
+#define PLL_FREQ_1200                  0x2AE5F002 /* 1200 */
+#define PLL_FREQ_2000                  0x2FC9F002 /* 2000 */
+#define PLL_FREQ_2200                  0x2AC57001 /* 2200 */
+#define PLL_FREQ_2400                  0x2AE5F001 /* 2400 */
+
+/* CPU PLL control registers */
+#define AP807_CPU_PLL_CTRL(cluster)    \
+                       (MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster)))
+
+#define AP807_CPU_PLL_PARAM(cluster)   AP807_CPU_PLL_CTRL(cluster)
+#define AP807_CPU_PLL_CFG(cluster)     (AP807_CPU_PLL_CTRL(cluster) + 0x4)
+#define AP807_CPU_PLL_CFG_BYPASS_MODE  (0x1)
+#define AP807_CPU_PLL_CFG_USE_REG_FILE (0x1 << 9)
+
+static void pll_set_freq(unsigned int freq_val)
+{
+       int i;
+
+       for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+               mmio_write_32(AP807_CPU_PLL_CFG(i),
+                             AP807_CPU_PLL_CFG_USE_REG_FILE);
+               mmio_write_32(AP807_CPU_PLL_CFG(i),
+                             AP807_CPU_PLL_CFG_USE_REG_FILE |
+                             AP807_CPU_PLL_CFG_BYPASS_MODE);
+               mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val);
+               mmio_write_32(AP807_CPU_PLL_CFG(i),
+                             AP807_CPU_PLL_CFG_USE_REG_FILE);
+       }
+}
+
+/* Switch to ARO from PLL in ap807 */
+static void aro_to_pll(void)
+{
+       unsigned int reg;
+       int i;
+
+       for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) {
+               /* switch from ARO to PLL */
+               reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+               reg |= AP807_CPU_ARO_SEL_PLL_MASK;
+               mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+
+               mdelay(100);
+
+               /* disable ARO clk driver */
+               reg = mmio_read_32(AP807_CPU_ARO_CTRL(i));
+               reg |= (AP807_CPU_ARO_CLK_EN_MASK);
+               mmio_write_32(AP807_CPU_ARO_CTRL(i), reg);
+       }
+}
+
+/* switch from ARO to PLL
+ * in case of default frequency option, configure PLL registers
+ * to be aligned with new default frequency.
+ */
+void ap807_clocks_init(unsigned int freq_option)
+{
+       /* Switch from ARO to PLL */
+       aro_to_pll();
+
+       /* Modifications in frequency table:
+        * 0x0: 764x: change to 2000 MHz.
+        * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400.
+        * 0x3: 3900/744x/764x change to 1200 MHz.
+        */
+       switch (freq_option) {
+       case CPU_2000_DDR_1200_RCLK_1200:
+               pll_set_freq(PLL_FREQ_2000);
+               break;
+       default:
+               break;
+       }
+}
diff --git a/include/drivers/marvell/ap807_clocks_init.h b/include/drivers/marvell/ap807_clocks_init.h
new file mode 100644 (file)
index 0000000..4353b83
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ * https://spdx.org/licenses
+ */
+
+#ifndef AP807_INIT_CLOCKS_H
+#define AP807_INIT_CLOCKS_H
+
+void ap807_clocks_init(unsigned int freq_option);
+
+#endif /* AP807_INIT_CLOCKS_H */
+
index 6136a1f596685d0222dcf9dba4be7457c0bcbf69..6b2b353585677259e025f872764802876f0239ed 100644 (file)
@@ -60,14 +60,15 @@ BLE_PORTING_SOURCES :=      $(PLAT_FAMILY_BASE)/$(PLAT)/board/dram_port.c \
 
 MARVELL_MOCHI_DRV      +=      $(MARVELL_DRV_BASE)/mochi/cp110_setup.c
 
-BLE_SOURCES            :=      drivers/mentor/i2c/mi2cv.c                      \
-                               $(PLAT_COMMON_BASE)/plat_ble_setup.c            \
-                               $(MARVELL_MOCHI_DRV)                           \
-                               $(PLAT_COMMON_BASE)/plat_pm.c                   \
-                               $(MARVELL_DRV_BASE)/thermal.c                   \
-                               $(PLAT_COMMON_BASE)/plat_thermal.c              \
-                               $(BLE_PORTING_SOURCES)                          \
-                               $(MARVELL_DRV_BASE)/ccu.c                       \
+BLE_SOURCES            :=      drivers/mentor/i2c/mi2cv.c              \
+                               $(PLAT_COMMON_BASE)/plat_ble_setup.c    \
+                               $(MARVELL_MOCHI_DRV)                    \
+                               $(PLAT_COMMON_BASE)/plat_pm.c           \
+                               $(MARVELL_DRV_BASE)/ap807_clocks_init.c \
+                               $(MARVELL_DRV_BASE)/thermal.c           \
+                               $(PLAT_COMMON_BASE)/plat_thermal.c      \
+                               $(BLE_PORTING_SOURCES)                  \
+                               $(MARVELL_DRV_BASE)/ccu.c               \
                                $(MARVELL_DRV_BASE)/io_win.c
 
 BL1_SOURCES            +=      $(PLAT_COMMON_BASE)/aarch64/plat_helpers.S \
index 7438f69cce3957b8a9ee355ec7483d346f6fe796..07d6cad9bebf7c386910e9d7b4e86d4b00a79f2b 100644 (file)
 #include <mv_ddr_if.h>
 #include <mvebu_def.h>
 #include <plat_marvell.h>
+#include "ap807_clocks_init.h"
 
 /* Register for skip image use */
 #define SCRATCH_PAD_REG2               0xF06F00A8
 #define SCRATCH_PAD_SKIP_VAL           0x01
 #define NUM_OF_GPIO_PER_REG 32
 
-#define MMAP_SAVE_AND_CONFIG   0
-#define MMAP_RESTORE_SAVED     1
+#define MMAP_SAVE_AND_CONFIG           0
+#define MMAP_RESTORE_SAVED             1
 
 /* SAR clock settings */
 #define MVEBU_AP_GEN_MGMT_BASE         (MVEBU_RFU_BASE + 0x8000)
                                         (0x2c2 << 3) | \
                                         (0x1 << AVS_SOFT_RESET_OFFSET) | \
                                         (0x1 << AVS_ENABLE_OFFSET))
+/* VDD is 0.88V for 2GHz clock */
+#define AVS_A3900_HIGH_CLK_VALUE       ((0x80 << 24) | \
+                                        (0x2f5 << 13) | \
+                                        (0x2f5 << 3) | \
+                                        (0x1 << AVS_SOFT_RESET_OFFSET) | \
+                                        (0x1 << AVS_ENABLE_OFFSET))
 
 #define MVEBU_AP_EFUSE_SRV_CTRL_REG    (MVEBU_AP_GEN_MGMT_BASE + 0x8)
 #define EFUSE_SRV_CTRL_LD_SELECT_OFFS  6
 #define EFUSE_SRV_CTRL_LD_SEL_USER_MASK        (1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
 
-/* Notify bootloader on DRAM setup */
-#define AP807_CPU_ARO_0_CTRL_0         (MVEBU_RFU_BASE + 0x82A8)
-#define AP807_CPU_ARO_1_CTRL_0         (MVEBU_RFU_BASE + 0x8D00)
-
-/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
-#define AP807_CPU_ARO_CLK_EN_OFFSET    0
-#define AP807_CPU_ARO_CLK_EN_MASK      (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
-
-/* 0 - ARO is the clock source, 1 - PLL is the clock source */
-#define AP807_CPU_ARO_SEL_PLL_OFFSET   5
-#define AP807_CPU_ARO_SEL_PLL_MASK     (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
 
 /*
  * - Identification information in the LD-0 eFuse:
        #define EFUSE_AP_LD0_WP_MASK            0x3FF
 #endif
 
-#define EFUSE_AP_LD0_SVC4_OFFS         42              /* LD0[112:105] */
+#define EFUSE_AP_LD0_SVC4_OFFS                 42      /* LD0[112:105] */
 
-#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
+#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS         4
 
 /* Return the AP revision of the chip */
 static unsigned int ble_get_ap_type(void)
@@ -207,37 +203,44 @@ static void ble_plat_mmap_config(int restore)
  */
 static void ble_plat_avs_config(void)
 {
-       uint32_t reg_val, device_id;
+       uint32_t freq_mode, device_id;
+       uint32_t avs_val = 0;
 
+       freq_mode =
+               SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+                                                FREQ_MODE_AP_SAR_REG_NUM)));
        /* Check which SoC is running and act accordingly */
        if (ble_get_ap_type() == CHIP_ID_AP807) {
-               VERBOSE("AVS: Setting AP807 AVS CTRL to 0x%x\n",
-                       AVS_A3900_CLK_VALUE);
-               mmio_write_32(AVS_EN_CTRL_REG, AVS_A3900_CLK_VALUE);
-               return;
+               /* Increase CPU voltage for higher CPU clock */
+               if (freq_mode == CPU_2000_DDR_1200_RCLK_1200)
+                       avs_val = AVS_A3900_HIGH_CLK_VALUE;
+               else
+                       avs_val = AVS_A3900_CLK_VALUE;
+       } else {
+               /* Check which SoC is running and act accordingly */
+               device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
+               switch (device_id) {
+               case MVEBU_80X0_DEV_ID:
+               case MVEBU_80X0_CP115_DEV_ID:
+                       /* Always fix the default AVS value on A80x0 */
+                       avs_val = AVS_A8K_CLK_VALUE;
+                       break;
+               case MVEBU_70X0_DEV_ID:
+               case MVEBU_70X0_CP115_DEV_ID:
+                       /* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
+                       if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
+                           (freq_mode < CPU_DDR_RCLK_INVALID))
+                               avs_val = AVS_A7K_LOW_CLK_VALUE;
+                       break;
+               default:
+                       ERROR("Unsupported Device ID 0x%x\n", device_id);
+                       return;
+               }
        }
 
-       /* Check which SoC is running and act accordingly */
-       device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
-       switch (device_id) {
-       case MVEBU_80X0_DEV_ID:
-       case MVEBU_80X0_CP115_DEV_ID:
-               /* Set the new AVS value - fix the default one on A80x0 */
-               mmio_write_32(AVS_EN_CTRL_REG, AVS_A8K_CLK_VALUE);
-               break;
-       case MVEBU_70X0_DEV_ID:
-       case MVEBU_70X0_CP115_DEV_ID:
-               /* Only fix AVS for CPU clocks lower than 1600MHz on A70x0 */
-               reg_val = mmio_read_32(MVEBU_AP_SAR_REG_BASE(
-                                               FREQ_MODE_AP_SAR_REG_NUM));
-               reg_val &= SAR_CLOCK_FREQ_MODE_MASK;
-               reg_val >>= SAR_CLOCK_FREQ_MODE_OFFSET;
-               if ((reg_val > CPU_1600_DDR_900_RCLK_900_2) &&
-                   (reg_val < CPU_DDR_RCLK_INVALID))
-                       mmio_write_32(AVS_EN_CTRL_REG, AVS_A7K_LOW_CLK_VALUE);
-               break;
-       default:
-               ERROR("Unsupported Device ID 0x%x\n", device_id);
+       if (avs_val) {
+               VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
+               mmio_write_32(AVS_EN_CTRL_REG, avs_val);
        }
 }
 
@@ -543,35 +546,11 @@ static int  ble_skip_current_image(void)
 }
 #endif
 
-/* Switch to ARO from PLL in ap807 */
-static void aro_to_pll(void)
-{
-       unsigned int reg;
-
-       /* switch from ARO to PLL */
-       reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
-       reg |= AP807_CPU_ARO_SEL_PLL_MASK;
-       mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
-       reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
-       reg |= AP807_CPU_ARO_SEL_PLL_MASK;
-       mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-
-       mdelay(1000);
-
-       /* disable ARO clk driver */
-       reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
-       reg |= (AP807_CPU_ARO_CLK_EN_MASK);
-       mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
-
-       reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
-       reg |= (AP807_CPU_ARO_CLK_EN_MASK);
-       mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
-}
 
 int ble_plat_setup(int *skip)
 {
        int ret;
+       unsigned int freq_mode;
 
        /* Power down unused CPUs */
        plat_marvell_early_cpu_powerdown();
@@ -598,9 +577,14 @@ int ble_plat_setup(int *skip)
        /* Setup AVS */
        ble_plat_svc_config();
 
+       /* read clk option from sampled-at-reset register */
+       freq_mode =
+               SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
+                                                FREQ_MODE_AP_SAR_REG_NUM)));
+
        /* work with PLL clock driver in AP807 */
        if (ble_get_ap_type() == CHIP_ID_AP807)
-               aro_to_pll();
+               ap807_clocks_init(freq_mode);
 
        /* Do required AP setups for BLE stage */
        ap_ble_init();